package xyz.heyaoshare.core.service.system.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.CacheableServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xyz.heyaoshare.common.constants.CacheKey;
import xyz.heyaoshare.common.entity.bo.ResultPage;
import xyz.heyaoshare.core.controller.system.dict.vo.req.*;
import xyz.heyaoshare.core.controller.system.dict.vo.resp.DictTypeDetailRespVO;
import xyz.heyaoshare.core.controller.system.dict.vo.resp.DictTypeListRespVO;
import xyz.heyaoshare.core.controller.system.dict.vo.resp.DictTypePageRespVO;
import xyz.heyaoshare.core.entity.system.DictData;
import xyz.heyaoshare.core.entity.system.DictType;
import xyz.heyaoshare.core.mapper.system.DictTypeMapper;
import xyz.heyaoshare.core.service.system.DictTypeService;
import xyz.heyaoshare.utils.BeanUtils;
import xyz.heyaoshare.utils.StrUtils;

import java.util.List;

import static xyz.heyaoshare.exceptions.code.ErrorInfo.*;
import static xyz.heyaoshare.exceptions.customize.ServerException.exception;

/**
 * 字典类型 Service 实现类
 * @author YueHe
 * @version 0.0.1
 * @since 2025/6/25 下午2:07
 */
@Slf4j
@Service
@CacheConfig(cacheNames = CacheKey.DICT_TYPE_SERVICE)
public class DictTypeServiceImpl extends CacheableServiceImpl<DictTypeMapper, DictType> implements DictTypeService {

    @Resource
    private DictTypeMapper dictTypeMapper;

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public Boolean insert(DictTypeInsertReqVO reqVO) {
        // 1.校验类型名是否重复
        long count = QueryChain.of(DictType.class).eq(DictType::getType, reqVO.getType()).count();
        if (count > 0) throw exception(DICT_TYPE_REPEAT);

        // 2.插入数据
        try {
            DictType dictType = new DictType()
                    .setName(reqVO.getName())
                    .setType(reqVO.getType())
                    .setSort(reqVO.getSort())
                    .setRemark(reqVO.getRemark());
            dictTypeMapper.insert(dictType);

            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("新增字典类型失败", e);
            throw exception(INSERT_DICT_TYPE_FAILED);
        }
    }

    @Override
    public ResultPage<DictTypePageRespVO> selectPage(DictTypePageReqVO reqVO) {
        // 1.查询数据
        Page<DictType> page = QueryChain.of(DictType.class)
                .like(DictType::getName, reqVO.getName(), StrUtils.isNotBlank(reqVO.getName()))
                .like(DictType::getType, reqVO.getType(), StrUtils.isNotBlank(reqVO.getType()))
                .orderBy(DictType::getSort, Boolean.FALSE)
                .orderBy(DictType::getCreateTime, Boolean.FALSE)
                .page(new Page<>(reqVO.getPage(), reqVO.getSize()));

        // 2.转换数据
        List<DictTypePageRespVO> items = BeanUtils.copyToList(page.getRecords(), DictTypePageRespVO.class);

        // 3.返回数据
        return ResultPage.result(page.getTotalRow(), items);
    }

    @Override
    @Cacheable
    public List<DictTypeListRespVO> selectList(DictTypeListReqVO reqVO) {
        // 1.查询数据
        List<DictType> list = QueryChain.of(dictTypeMapper).orderBy(DictType::getSort, Boolean.FALSE).list();

        // 2.转换并返回数据
        return BeanUtils.copyToList(list, DictTypeListRespVO.class);
    }

    @Override
    @Cacheable
    public DictTypeDetailRespVO selectDetail(DictTypeDetailReqVO reqVO) {
        DictType dictType = dictTypeMapper.selectOneById(reqVO.getDictTypeId());
        if (dictType == null) throw exception(DICT_TYPE_NOT_EXIST);

        return BeanUtils.copyProperties(dictType, DictTypeDetailRespVO.class);
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(DictTypeDeleteReqVO reqVO) {
        try {
            // 字典类型和字典关联的数据一起删除
            UpdateChain.of(DictType.class).in(DictType::getId, reqVO.getId()).remove();
            UpdateChain.of(DictData.class).in(DictData::getDictTypeId, reqVO.getId()).remove();
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("删除字典失败", e);
            throw exception(DELETE_DICT_TYPE_FAILED);
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateData(DictTypeUpdateReqVO reqVO) {
        // 1.校验类型名是否重复
        long count = QueryChain.of(DictType.class).ne(DictType::getId, reqVO.getId()).eq(DictType::getType, reqVO.getType()).count();
        if (count > 0) throw exception(DICT_TYPE_REPEAT);

        // 2.更新数据
        try {
            UpdateChain.of(DictType.class)
                    .set(DictType::getName, reqVO.getName())
                    .set(DictType::getType, reqVO.getType())
                    .set(DictType::getSort, reqVO.getSort())
                    .set(DictType::getRemark, reqVO.getRemark())
                    .eq(DictType::getId, reqVO.getId())
                    .update();
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("更新字典类型失败", e);
            throw exception(UPDATE_DICT_TYPE_FAILED);
        }
    }

}